use anyhow::Result;
use rusqlite::{Connection, Result as SqliteResult, OptionalExtension};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Account {
    pub id: String,
    pub username: String,
    pub nickname: String,
    pub phone: String,
    pub status: String,
    pub followers: i32,
    pub following: i32,
    pub posts: i32,
    pub last_login: Option<String>,
    pub cookies: Option<String>,
    pub token: Option<String>,
    pub is_current: bool,
    pub created_at: String,
    pub updated_at: String,
}

pub struct Database {
    db_path: String,
}

impl Database {
    pub fn new() -> Result<Self> {
        let db_path = std::env::current_dir()?.join("accounts.db");
        let db = Database {
            db_path: db_path.to_string_lossy().to_string(),
        };
        db.init_tables()?;
        Ok(db)
    }

    fn get_connection(&self) -> SqliteResult<Connection> {
        Connection::open(&self.db_path)
    }

    fn init_tables(&self) -> Result<()> {
        let conn = self.get_connection()?;
        conn.execute(
            "CREATE TABLE IF NOT EXISTS accounts (
                id TEXT PRIMARY KEY,
                username TEXT NOT NULL,
                nickname TEXT NOT NULL,
                phone TEXT UNIQUE NOT NULL,
                status TEXT NOT NULL,
                followers INTEGER DEFAULT 0,
                following INTEGER DEFAULT 0,
                posts INTEGER DEFAULT 0,
                last_login TEXT,
                cookies TEXT,
                token TEXT,
                is_current BOOLEAN DEFAULT FALSE,
                created_at TEXT NOT NULL,
                updated_at TEXT NOT NULL
            )",
            [],
        )?;
        Ok(())
    }

    pub fn get_accounts(&self) -> Result<Vec<Account>> {
        let conn = self.get_connection()?;
        let mut stmt = conn.prepare("SELECT * FROM accounts ORDER BY created_at DESC")?;
        let accounts = stmt.query_map([], |row| {
            Ok(Account {
                id: row.get(0)?,
                username: row.get(1)?,
                nickname: row.get(2)?,
                phone: row.get(3)?,
                status: row.get(4)?,
                followers: row.get(5)?,
                following: row.get(6)?,
                posts: row.get(7)?,
                last_login: row.get(8)?,
                cookies: row.get(9)?,
                token: row.get(10)?,
                is_current: row.get(11)?,
                created_at: row.get(12)?,
                updated_at: row.get(13)?,
            })
        })?
        .collect::<SqliteResult<Vec<_>>>()?;
        Ok(accounts)
    }

    pub fn add_account(&self, account: &Account) -> Result<()> {
        let conn = self.get_connection()?;
        conn.execute(
            "INSERT INTO accounts (id, username, nickname, phone, status, followers, following, posts, last_login, cookies, token, is_current, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
            [
                &account.id,
                &account.username,
                &account.nickname,
                &account.phone,
                &account.status,
                &account.followers.to_string(),
                &account.following.to_string(),
                &account.posts.to_string(),
                &account.last_login.as_deref().unwrap_or("").to_string(),
                &account.cookies.as_deref().unwrap_or("").to_string(),
                &account.token.as_deref().unwrap_or("").to_string(),
                &account.is_current.to_string(),
                &account.created_at,
                &account.updated_at,
            ],
        )?;
        Ok(())
    }

    pub fn update_account(&self, id: &str, updates: &Account) -> Result<()> {
        let conn = self.get_connection()?;
        conn.execute(
            "UPDATE accounts SET username = ?, nickname = ?, phone = ?, status = ?, followers = ?, following = ?, posts = ?, last_login = ?, cookies = ?, token = ?, is_current = ?, updated_at = ? WHERE id = ?",
            [
                &updates.username,
                &updates.nickname,
                &updates.phone,
                &updates.status,
                &updates.followers.to_string(),
                &updates.following.to_string(),
                &updates.posts.to_string(),
                &updates.last_login.as_deref().unwrap_or("").to_string(),
                &updates.cookies.as_deref().unwrap_or("").to_string(),
                &updates.token.as_deref().unwrap_or("").to_string(),
                &updates.is_current.to_string(),
                &updates.updated_at,
                id,
            ],
        )?;
        Ok(())
    }

    pub fn delete_account(&self, id: &str) -> Result<()> {
        let conn = self.get_connection()?;
        conn.execute("DELETE FROM accounts WHERE id = ?", [id])?;
        Ok(())
    }

    pub fn get_account(&self, id: &str) -> Result<Option<Account>> {
        let conn = self.get_connection()?;
        let account = conn.query_row(
            "SELECT * FROM accounts WHERE id = ?",
            [id],
            |row| {
                Ok(Account {
                    id: row.get(0)?,
                    username: row.get(1)?,
                    nickname: row.get(2)?,
                    phone: row.get(3)?,
                    status: row.get(4)?,
                    followers: row.get(5)?,
                    following: row.get(6)?,
                    posts: row.get(7)?,
                    last_login: row.get(8)?,
                    cookies: row.get(9)?,
                    token: row.get(10)?,
                    is_current: row.get(11)?,
                    created_at: row.get(12)?,
                    updated_at: row.get(13)?,
                })
            },
        ).optional()?;
        Ok(account)
    }

    pub fn get_account_by_phone(&self, phone: &str) -> Result<Option<Account>> {
        let conn = self.get_connection()?;
        let account = conn.query_row(
            "SELECT * FROM accounts WHERE phone = ?",
            [phone],
            |row| {
                Ok(Account {
                    id: row.get(0)?,
                    username: row.get(1)?,
                    nickname: row.get(2)?,
                    phone: row.get(3)?,
                    status: row.get(4)?,
                    followers: row.get(5)?,
                    following: row.get(6)?,
                    posts: row.get(7)?,
                    last_login: row.get(8)?,
                    cookies: row.get(9)?,
                    token: row.get(10)?,
                    is_current: row.get(11)?,
                    created_at: row.get(12)?,
                    updated_at: row.get(13)?,
                })
            },
        ).optional()?;
        Ok(account)
    }

    pub fn get_current_account(&self) -> Result<Option<Account>> {
        let conn = self.get_connection()?;
        let account = conn.query_row(
            "SELECT * FROM accounts WHERE is_current = 1",
            [],
            |row| {
                Ok(Account {
                    id: row.get(0)?,
                    username: row.get(1)?,
                    nickname: row.get(2)?,
                    phone: row.get(3)?,
                    status: row.get(4)?,
                    followers: row.get(5)?,
                    following: row.get(6)?,
                    posts: row.get(7)?,
                    last_login: row.get(8)?,
                    cookies: row.get(9)?,
                    token: row.get(10)?,
                    is_current: row.get(11)?,
                    created_at: row.get(12)?,
                    updated_at: row.get(13)?,
                })
            },
        ).optional()?;
        Ok(account)
    }

    pub fn set_all_accounts_not_current(&self) -> Result<()> {
        let conn = self.get_connection()?;
        conn.execute("UPDATE accounts SET is_current = 0", [])?;
        Ok(())
    }

    pub fn set_current_account(&self, id: &str) -> Result<()> {
        let conn = self.get_connection()?;
        conn.execute("UPDATE accounts SET is_current = 1 WHERE id = ?", [id])?;
        Ok(())
    }
} 